home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 020 / amigatoatari / convert.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  10KB  |  572 lines

  1. /* convert.c */
  2. #include <stdio.h>
  3. #include "convert.h"
  4.  
  5. extern int debug;    /* 1: print debugging messages */
  6. extern int printing;    /* 1: print conversion statistics */
  7.  
  8. Hinfo *ahinfo();
  9.  
  10.  
  11. /* hunk information */
  12. Hinfo **hunk;        /* -> vector of ptrs to Hinfo structs */
  13. Hinfo *firsthunk;    /* -> first hunk */
  14. int nhunks;        /* #hunks in input file */
  15. int curhunk;        /* current hunk# */
  16. int hvalid;        /* state variable (to bump curhunk) */
  17. long filpos;        /* position in input file */
  18. long siz[3];        /* segment sizes */
  19.  
  20. /* relocation (fixup) information */
  21. long rsize;        /* total size of all relocation information */
  22. long *rbuf;        /* -> buffer for relocation information */
  23. long *rpos;        /* current position in relocation info buffer */
  24.  
  25. char buf[BUFFERSIZE];    /* buffer for copying stuff */
  26.  
  27.  
  28. /*
  29.  * Convert AMIG* binary loadfile to GEMDOS .PRG executable.
  30.  */
  31. convert(ifd, ofd)
  32. int ifd, ofd;
  33. {
  34.     /* init globals */
  35.     hunk = (Hinfo **)NULL;
  36.     firsthunk = (Hinfo *)NULL;
  37.     hvalid = nhunks = curhunk = 0;
  38.     filpos = 0L;
  39.     rsize = 0L;
  40.  
  41.     pass1(ifd);
  42.     if (curhunk < nhunks)
  43.     panic("Bugcheck: not enough hunks in input body.");
  44.     bind();
  45.  
  46.     if ((rbuf = (long *)malloc((int)rsize)) == NULL)
  47.     allerr((int)rsize);
  48.     rpos = rbuf;
  49.  
  50.     output(ifd, ofd);
  51.     reloc(ifd, ofd);
  52.     release();
  53. }
  54.  
  55.  
  56. /*
  57.  * Parse hunks in AMIG* binary loadfile,
  58.  * gather information about it.
  59.  */
  60. pass1(ifd)
  61. int ifd;
  62. {
  63.     long lw, junk;
  64.     Hinfo *h;
  65.  
  66. DEBUG("~ pass1()\n");
  67.  
  68.     for(;;)
  69.     {
  70.     if (readlong(ifd, &lw) == EOF)
  71.         break;
  72.  
  73.     switch ((int)lw)
  74.     {
  75.         case HUNKUNIT:
  76.         case HUNKNAME:
  77.         DEBUG("~\tHUNKUNIT or HUNKNAME\n");
  78.         getlong(ifd, &lw);
  79.         skip(ifd, lw * 4);
  80.         break;
  81.  
  82.         case HUNKCODE:
  83.         chkhunk();
  84.         h = hunk[curhunk];
  85.         getlong(ifd, &lw);        /* get size (in longs) */
  86.         lw *= 4;
  87.         h->hsize = lw;
  88.         h->hpos = filpos;
  89.         h->htype = TEXT;
  90.         skip(ifd, lw);
  91.         if (debug) dumphinfo(h);
  92.         break;
  93.  
  94.         case HUNKDATA:
  95.         chkhunk();
  96.         h = hunk[curhunk];
  97.         getlong(ifd, &lw);        /* get size (in longs) */
  98.         lw *= 4;
  99.         h->hsize = lw;
  100.         h->hpos = filpos;
  101.         h->htype = DATA;
  102.         skip(ifd, lw);
  103.         if (debug) dumphinfo(h);
  104.         break;
  105.  
  106.         case HUNKBSS:
  107.         chkhunk();
  108.         h = hunk[curhunk];
  109.         getlong(ifd, &lw);        /* get size (in longs) */
  110.         h->hsize = lw * 4;
  111.         h->htype = BSS;
  112.         if (debug) dumphinfo(h);
  113.         break;
  114.  
  115.         case HUNKR32:
  116.         h = hunk[curhunk];
  117.         for (;;)
  118.         {
  119.             getlong(ifd, &lw);
  120.             if (!lw) break;
  121.             lw = (lw + 1) * 4;
  122.             h->hrsize += lw + 4;
  123.             skip(ifd, lw);
  124.         }
  125.         h->hrsize += 4;
  126.         rsize += h->hrsize + 4;
  127.         if(debug)printf("~\thrsize = %ld\n", h->hrsize);
  128.         break;
  129.  
  130.         case HUNKR16:
  131.         panic("16-bit relocation not supported.");
  132.         break;
  133.  
  134.         case HUNKR8:
  135.         panic("8-bit relocation not supported.");
  136.         break;
  137.  
  138.         case HUNKEXT:
  139.         panic("External symbols not supported.");
  140.         break;
  141.  
  142.         case HUNKSYMBOL:
  143.         panic("Symbols not supported.");
  144.         break;
  145.  
  146.         case HUNKDEBUG:
  147.         panic("Debug blocks not supported.");
  148.         break;
  149.  
  150.         case HUNKEND:
  151.         if (hvalid)
  152.         {
  153.             hvalid = 0;
  154.             ++curhunk;
  155.         }
  156.         if(debug)printf("~HUNKEND, curhunk = %d\n", curhunk);
  157.         break;
  158.  
  159.         case HUNKHEADER:
  160.         header(ifd);
  161.         break;
  162.  
  163.         case HUNKOVERLAY:
  164.         panic("Overlays not supported.");
  165.         break;
  166.  
  167.         case HUNKBREAK:
  168.         panic("Breaks (overlays) not supported.");
  169.         break;
  170.     }
  171.     }
  172. }
  173.  
  174.  
  175. /*
  176.  * Sanity check about hunk adjacency (which may not be a
  177.  * problem) and hunk number range.
  178.  */
  179. chkhunk()
  180. {
  181.     if (hvalid)
  182.     panic("Bugcheck: two adjacent hunks w/o HUNKEND!");
  183.     if (curhunk >= nhunks)
  184.     panic("Bugcheck: too many hunks!");
  185.     hvalid = 1;
  186. }
  187.  
  188.  
  189. /*
  190.  * Read hunk header,
  191.  * get info for global vars.
  192.  *
  193.  */
  194. header(fd)
  195. int fd;
  196. {
  197.     long lw, *p;
  198.     long htabsize, firsthunk, lasthunk;
  199.     unsigned int i, j;
  200.  
  201.     /*
  202.      * Skip library names.
  203.      */
  204.     for (;;)
  205.     {
  206.     getlong(fd, &lw);
  207.     if (!lw) break;
  208.     skip(fd, lw*4);
  209.     }
  210.  
  211.     /* more random header info */
  212.     getlong(fd, &htabsize);
  213.     getlong(fd, &firsthunk);
  214.     getlong(fd, &lasthunk);
  215.     if (debug)
  216.     printf("~\thtabsize = %ld\n\tfirsthunk = %ld\n\tlasthunk = %ld\n",
  217.         htabsize, firsthunk, lasthunk);
  218.  
  219.     /* alloc space for hunk database */
  220.     nhunks = (unsigned)(lasthunk - firsthunk + 1);
  221.     hunk = (Hinfo **)malloc(nhunks * sizeof(Hinfo));
  222.     if (hunk == NULL)
  223.     allerr(nhunks * sizeof(Hinfo));
  224.  
  225.     for (j = 0; j < nhunks; ++j)
  226.     {
  227.     hunk[j] = ahinfo();
  228.     hunk[j]->hunkno = j;
  229.     getlong(fd, &hunk[j]->hsize);
  230.     if(debug) printf("~\t%d hsize = %ld ($%lx)\n",
  231.         j, hunk[j]->hsize, hunk[j]->hsize);
  232.     }
  233. }
  234.  
  235.  
  236. /*
  237.  * Compute hunk order and starting addresses.
  238.  */
  239. bind()
  240. {
  241.     int typ, hnk;
  242.     long addr;
  243.     Hinfo *hptr;
  244.  
  245. DEBUG("~ bind()\n");
  246.     addr = 0L;
  247.     hptr = firsthunk;
  248.     for (typ = 0; typ < 3; ++typ)
  249.     {
  250.     siz[typ] = 0L;
  251.     for (hnk = 0; hnk < nhunks; ++hnk)
  252.         if (hunk[hnk]->htype == typ)
  253.         {
  254.         if (firsthunk == (Hinfo *)NULL)
  255.             hptr = firsthunk = hunk[hnk];
  256.             else {
  257.             hptr->hnext = hunk[hnk];
  258.             hptr = hunk[hnk];
  259.             }
  260.         siz[typ] += hptr->hsize;
  261.         hptr->haddr = addr;
  262.         addr += hptr->hsize;
  263.         if(debug)
  264.             printf("~\thunk[%d]->haddr = $%lx\n", hnk, hptr->haddr);
  265.         }
  266.     }
  267.  
  268.     if(printing)
  269.     printf("text %ld ($%lx), data %ld ($%lx), bss %ld ($%lx)\n",
  270.         siz[0], siz[0], siz[1], siz[1], siz[2], siz[2]);
  271. }
  272.  
  273.  
  274. /*
  275.  * Generate the GEMDOS output file.
  276.  */
  277. output(ifd, ofd)
  278. int ifd, ofd;
  279. {
  280.     int i;
  281.     Hinfo *hu;
  282.  
  283. DEBUG("~ output()\n");
  284.     /*
  285.      * Write .PRG header.
  286.      */
  287.     writeword(ofd, 0x601a);
  288.     for (i = 0; i < 3; i++)
  289.     writelong(ofd, siz[i]);
  290.     for (i = 0; i < 7; i++)
  291.     writeword(ofd, 0x0000);
  292.  
  293.     for (hu = firsthunk; hu != NULL; hu = hu->hnext)
  294.     if (hu->htype == TEXT || hu->htype == DATA)
  295.     {
  296.         lseek(ifd, hu->hpos, 0);
  297.         randw(ifd, hu->hsize, ofd);
  298.  
  299.         if (hu->hrsize)
  300.         {
  301.         lseek(ifd, 4L, 1);
  302.         *rpos++ = hu->hunkno;
  303.         if (read(ifd, rpos, (int)hu->hrsize) != (int)hu->hrsize)
  304.             panic("Reloc info read error.");
  305. if(debug)printf("~ relocsiz = %ld\n", hu->hrsize);
  306.         rpos += hu->hrsize >> 2;
  307.         }
  308.     }
  309. }
  310.  
  311.  
  312. /*
  313.  * Generate relocation information
  314.  * (at the end of the output file).
  315.  */
  316. reloc(ifd, ofd)
  317. int ifd, ofd;
  318. {
  319.     int cmplong();
  320.     long cvt2long();
  321.     long *rp, *drp;
  322.     char *crp, c;
  323.     int i, hno, nel;
  324.     long count, base, lw, addr;
  325. DEBUG("~ reloc()\n");
  326.  
  327. if (debug)
  328.   {
  329.     i = 0;
  330.     for (crp = (char *)rbuf; crp < (char *)rpos; crp += 4)
  331.     {
  332.     if (!i) printf("~ ");
  333.     printf("%02x%02x%02x%02x",
  334.         crp[0]&0xff, crp[1]&0xff, crp[2]&0xff, crp[3]&0xff);
  335.     if (++i >= 8)
  336.     {
  337.         printf("\n");
  338.         i = 0;
  339.     } else putchar(' ');
  340.     }
  341.     putchar('\n');
  342.   }
  343.  
  344.     /*
  345.      * Go back into the .PRG file and add
  346.      * hunk starting-offsets to the longwords
  347.      * that must be fixed up.
  348.      * 28L is the size of the GEMDOS .PRG header.
  349.      */
  350.     for (rp = rbuf; rp < rpos;)
  351.     {
  352.     hno = *rp++;
  353. if(debug)printf("~    hno = %d\n", hno);
  354.     for (;;)
  355.         {
  356.         *rp = cvt2long(*rp);
  357.         if (!(count = *rp++)) break;
  358.         *rp = cvt2long(*rp);
  359.         base = hunk[(int)*rp++]->haddr;
  360. if(debug)printf("~        count = %ld, base = $%0lx\n", count, base);
  361.         while (count--)
  362.         {
  363.         *rp = cvt2long(*rp);
  364. if(debug)printf("~        seek(ifd) = %ld, seek(ofd) = %ld ",
  365.             hunk[hno]->hpos + *rp,
  366.             hunk[hno]->haddr + *rp + 28L);
  367.         lseek(ifd, hunk[hno]->hpos + *rp, 0);
  368.         lseek(ofd, hunk[hno]->haddr + *rp++ + 28L, 0);
  369.         readlong(ifd, &lw);
  370.         lw += base;
  371.         writelong(ofd, lw);
  372. if(debug)printf("lw = $%0lx\n", lw);
  373.         }
  374.     }
  375.     }
  376.  
  377.  
  378.     /*
  379.      * Compute and sort fixup offsets.
  380.      */
  381.     nel = 0;
  382.     drp = rbuf;
  383.     for (rp = rbuf; rp < rpos;)
  384.     {
  385.     hno = *rp++;
  386.     for (;;)
  387.     {
  388.         if (!(count = *rp++)) break;
  389.         ++rp;
  390.         while (count--)
  391.         {
  392.         *drp++ = hunk[hno]->haddr + *rp++;
  393.         ++nel;
  394.         }
  395.     }
  396.     }
  397.     rpos = drp;
  398.     qsort(rbuf, nel, 4, cmplong);
  399.  
  400. /* print sorted info */
  401. if(debug)
  402.   {
  403.     i = 0;
  404.     for (rp = rbuf; rp < rpos; ++rp)
  405.     {
  406.     if (!i) printf("~ ");
  407.     printf("%08lx", *rp);
  408.     if (++i >= 8)
  409.     {
  410.         printf("\n");
  411.         i = 0;
  412.     } else putchar(' ');
  413.     }
  414.     putchar('\n');
  415.   }
  416.  
  417.  
  418.     /*
  419.      * Write GEMDOS relocation information
  420.      */
  421.     lseek(ofd, 0L, 2);                /* to end of file */
  422.     rp = rbuf;
  423.     while (rp < rpos)
  424.     {
  425.     /* write offset to first fixup */
  426.     if (rp == rbuf)
  427.     {
  428.         writelong(ofd, *rp);
  429.         addr = *rp++;
  430. if(debug)printf("$%lx\n", addr);
  431.         continue;
  432.     }
  433.  
  434.     if (addr >= *rp) panic("Bad relocation information.");
  435.     c = 254;
  436.     lw = *rp - addr;
  437.     addr = *rp++;
  438. if(debug)printf("$%lx:", lw);
  439.     while (lw > 254)
  440.     {
  441.         write(ofd, &c, 1);
  442.         lw -= 254L;
  443. if(debug)putchar('+');
  444.     }
  445.         c = (char)lw;
  446.     write(ofd, &c, 1);
  447. if(debug)printf("$%x\n", (int)lw);
  448.     }
  449.  
  450.     /*
  451.      * Terminate relocation list
  452.      */
  453.     c = 0;
  454.     write(ofd, &c, 1);
  455. }
  456.  
  457.  
  458. /*
  459.  * Compare two longs
  460.  * for qsort().
  461.  */
  462. cmplong(l1, l2)
  463. long *l1, *l2;
  464. {
  465.     return *l1 - *l2;
  466. }
  467.  
  468.  
  469. /*
  470.  * Allocate (and initialize) a Hinfo node.
  471.  */
  472. Hinfo *ahinfo()
  473. {
  474.     Hinfo *h;
  475.  
  476.     if (curhunk >= nhunks)
  477.     panic("curhunk >= nhunks, too many hunks!");
  478.  
  479.     if ((h = (Hinfo *)malloc(sizeof(Hinfo))) == NULL)
  480.     allerr(sizeof(Hinfo));
  481.     h->hsize = 0L;
  482.     h->hpos = 0L;
  483.     h->haddr = 0L;
  484.     h->hrsize = 0L;
  485.     h->htype = -1;
  486.     h->hrel = (long *)NULL;
  487.     h->hnext = (Hinfo *)NULL;
  488.  
  489.     return h;
  490. }
  491.  
  492.  
  493. /*
  494.  * Release memory used by hunk database.
  495.  */
  496. release()
  497. {
  498.     int i;
  499.  
  500.     for (i = 0; i < nhunks; ++i)
  501.     {
  502.     if (hunk[i]->hrel != NULL)
  503.         free(hunk[i]->hrel);
  504.     free(hunk[i]);
  505.     }
  506.     free(hunk);
  507. }
  508.  
  509.  
  510. /*
  511.  * Skip some of the input file
  512.  */
  513. skip(fd, count)
  514. int fd;
  515. long count;
  516. {
  517.     filpos += count;
  518.     lseek(fd, count, 1);
  519. }
  520.  
  521.  
  522. /*
  523.  * Out of memory (malloc() didn't work);
  524.  * complain and die.
  525.  */
  526. allerr(size)
  527. int size;
  528. {
  529.     fprintf (stderr, "malloc(%d) failed..\n", size);
  530.     panic("Allocation failure, heap exhausted, I give up!\n");
  531. }
  532.  
  533.  
  534. /*
  535.  * Print information about an Hinfo node.
  536.  */
  537. dumphinfo(h)
  538. Hinfo *h;
  539. {
  540.     printf("~\thsize = %ld ($%lx), hpos = %ld, haddr = %ld ($%lx)\n",
  541.         h->hsize, h->hsize, h->hpos, h->haddr, h->haddr);
  542.     printf("~\thtype = %d ", h->htype);
  543.     printf("hrel = $%lx, hnext = $%lx\n",
  544.         (long)h->hrel, (long)h->hnext);
  545. }
  546.  
  547.  
  548. /*
  549.  * Convert 68000 long to local long
  550.  */
  551. long cvt2long(lw)
  552. long lw;
  553. {
  554. #ifdef AMIGA
  555.     return (lw);
  556. #else
  557.     char *out, *in;
  558.     long olw;
  559.  
  560.     /*
  561.      * 8086/VAX conversion
  562.      */
  563.     in = (char *)&lw;
  564.     out = (char *)&olw;
  565.     out[0] = in[3];
  566.     out[1] = in[2];
  567.     out[2] = in[1];
  568.     out[3] = in[0];
  569.     return olw;
  570. #endif    /* AMIGA */
  571. }
  572.